{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Packages Imported\n"
     ]
    }
   ],
   "source": [
    "# Import Packages\n",
    "import numpy as np\n",
    "import tensorflow as tf\n",
    "import collections\n",
    "import argparse\n",
    "import time\n",
    "import os\n",
    "from six.moves import cPickle\n",
    "print (\"Packages Imported\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Text loaded from 'data/linux_kernel/input.txt'\n"
     ]
    }
   ],
   "source": [
    "# Load text\n",
    "# data_dir    = \"data/tinyshakespeare\"\n",
    "data_dir    = \"data/linux_kernel\"\n",
    "save_dir    = \"data/linux_kernel\"\n",
    "input_file  = os.path.join(data_dir, \"input.txt\")\n",
    "with open(input_file, \"r\") as f:\n",
    "    data = f.read()\n",
    "print (\"Text loaded from '%s'\" % (input_file))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Type of 'counter.items()' is <type 'list'> and length is 99\n",
      "[0/3] (' ', 171222)\n",
      "[1/3] ('$', 61)\n",
      "[2/3] ('(', 23412)\n",
      "[3/3] (',', 17025)\n",
      "[4/3] ('0', 4322)\n",
      " \n",
      "Type of 'count_pairs' is <type 'list'> and length is 99\n",
      "[0/3] (' ', 171222)\n",
      "[1/3] ('e', 113021)\n",
      "[2/3] ('t', 102154)\n",
      "[3/3] ('r', 76185)\n",
      "[4/3] ('i', 75486)\n"
     ]
    }
   ],
   "source": [
    "# Preprocess Text\n",
    "# First, count the number of characters\n",
    "counter = collections.Counter(data)\n",
    "count_pairs = sorted(counter.items(), key=lambda x: -x[1]) # <= Sort\n",
    "print (\"Type of 'counter.items()' is %s and length is %d\" \n",
    "       % (type(counter.items()), len(counter.items()))) \n",
    "for i in range(5):\n",
    "    print (\"[%d/%d]\" % (i, 3)), # <= This comma remove '\\n'\n",
    "    print (list(counter.items())[i])\n",
    "\n",
    "print (\" \")\n",
    "print (\"Type of 'count_pairs' is %s and length is %d\" \n",
    "       % (type(count_pairs), len(count_pairs))) \n",
    "for i in range(5):\n",
    "    print (\"[%d/%d]\" % (i, 3)), # <= This comma remove '\\n'\n",
    "    print (count_pairs[i])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {
    "collapsed": false,
    "scrolled": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Type of 'chars' is <type 'tuple'> and length is 99\n",
      "[0/3] chars[0] is ' '\n",
      "[1/3] chars[1] is 'e'\n",
      "[2/3] chars[2] is 't'\n",
      "[3/3] chars[3] is 'r'\n",
      "[4/3] chars[4] is 'i'\n",
      "\n",
      "Type of 'vocab' is <type 'dict'> and length is 99\n",
      "[0/3] vocab[' '] is 0\n",
      "[1/3] vocab['e'] is 1\n",
      "[2/3] vocab['t'] is 2\n",
      "[3/3] vocab['r'] is 3\n",
      "[4/3] vocab['i'] is 4\n"
     ]
    }
   ],
   "source": [
    "# Let's make dictionary\n",
    "chars, counts = zip(*count_pairs)\n",
    "vocab = dict(zip(chars, range(len(chars))))\n",
    "print (\"Type of 'chars' is %s and length is %d\" \n",
    "    % (type(chars), len(chars))) \n",
    "for i in range(5):\n",
    "    print (\"[%d/%d]\" % (i, 3)), # <= This comma remove '\\n'\n",
    "    print (\"chars[%d] is '%s'\" % (i, chars[i]))\n",
    "    \n",
    "print (\"\")\n",
    "\n",
    "print (\"Type of 'vocab' is %s and length is %d\" \n",
    "    % (type(vocab), len(vocab))) \n",
    "for i in range(5):\n",
    "    print (\"[%d/%d]\" % (i, 3)), # <= This comma remove '\\n'\n",
    "    print (\"vocab['%s'] is %s\" % (chars[i], vocab[chars[i]]))\n",
    "    \n",
    "# SAve chars and vocab\n",
    "with open(os.path.join(save_dir, 'chars_vocab.pkl'), 'wb') as f:\n",
    "    cPickle.dump((chars, vocab), f)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# chars[0] converts index to char\n",
    "# vocab['a'] converts char to index"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Type of 'corpus' is <type 'numpy.ndarray'>, shape is (1708871,), and length is 1708871\n",
      "\n",
      "'corpus' looks like [36 22  7  0 22  0  0 13  4  8]\n",
      "[0/10] chars[36] corresponds to '/'\n",
      "[1/10] chars[22] corresponds to '*'\n",
      "[2/10] chars[07] corresponds to '\n",
      "'\n",
      "[3/10] chars[00] corresponds to ' '\n",
      "[4/10] chars[22] corresponds to '*'\n",
      "[5/10] chars[00] corresponds to ' '\n",
      "[6/10] chars[00] corresponds to ' '\n",
      "[7/10] chars[13] corresponds to 'l'\n",
      "[8/10] chars[04] corresponds to 'i'\n",
      "[9/10] chars[08] corresponds to 'n'\n"
     ]
    }
   ],
   "source": [
    "# Now convert all text to index using vocab! \n",
    "corpus = np.array(list(map(vocab.get, data)))\n",
    "print (\"Type of 'corpus' is %s, shape is %s, and length is %d\" \n",
    "    % (type(corpus), corpus.shape, len(corpus)))\n",
    "\n",
    "check_len = 10\n",
    "print (\"\\n'corpus' looks like %s\" % (corpus[0:check_len]))\n",
    "for i in range(check_len):\n",
    "    _wordidx = corpus[i]\n",
    "    print (\"[%d/%d] chars[%02d] corresponds to '%s'\" \n",
    "           % (i, check_len, _wordidx, chars[_wordidx]))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "xdata is ... [36 22  7 ..., 11 25  3] and length is 1700000\n",
      "ydata is ... [22  7  0 ..., 25  3 36] and length is 1700000\n",
      "\n",
      "Type of 'xbatches' is <type 'list'> and length is 170\n",
      "Type of 'ybatches' is <type 'list'> and length is 170\n",
      "\n",
      "Type of 'temp' is <type 'list'> and length is 5\n",
      "Type of 'temp[0]' is <type 'numpy.ndarray'> and shape is (50, 200)\n",
      "Type of 'temp[1]' is <type 'numpy.ndarray'> and shape is (50, 200)\n",
      "Type of 'temp[2]' is <type 'numpy.ndarray'> and shape is (50, 200)\n",
      "Type of 'temp[3]' is <type 'numpy.ndarray'> and shape is (50, 200)\n",
      "Type of 'temp[4]' is <type 'numpy.ndarray'> and shape is (50, 200)\n"
     ]
    }
   ],
   "source": [
    "# Generate batch data \n",
    "batch_size  = 50\n",
    "seq_length  = 200\n",
    "num_batches = int(corpus.size / (batch_size * seq_length))\n",
    "# First, reduce the length of corpus to fit batch_size\n",
    "corpus_reduced = corpus[:(num_batches*batch_size*seq_length)]\n",
    "xdata = corpus_reduced\n",
    "ydata = np.copy(xdata)\n",
    "ydata[:-1] = xdata[1:]\n",
    "ydata[-1]  = xdata[0]\n",
    "print ('xdata is ... %s and length is %d' % (xdata, xdata.size))\n",
    "print ('ydata is ... %s and length is %d' % (ydata, xdata.size))\n",
    "print (\"\")\n",
    "\n",
    "# Second, make batch \n",
    "xbatches = np.split(xdata.reshape(batch_size, -1), num_batches, 1)\n",
    "ybatches = np.split(ydata.reshape(batch_size, -1), num_batches, 1)\n",
    "print (\"Type of 'xbatches' is %s and length is %d\" \n",
    "    % (type(xbatches), len(xbatches)))\n",
    "print (\"Type of 'ybatches' is %s and length is %d\" \n",
    "    % (type(ybatches), len(ybatches)))\n",
    "print (\"\")\n",
    "\n",
    "# How can we access to xbatches?? \n",
    "nbatch = 5\n",
    "temp = xbatches[0:nbatch]\n",
    "print (\"Type of 'temp' is %s and length is %d\" \n",
    "    % (type(temp), len(temp)))\n",
    "for i in range(nbatch):\n",
    "    temp2 = temp[i]\n",
    "    print (\"Type of 'temp[%d]' is %s and shape is %s\" % (i, type(temp2), temp2.shape,))\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Now, we are ready to make our RNN model with seq2seq"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Network Ready\n"
     ]
    }
   ],
   "source": [
    "# Important RNN parameters \n",
    "vocab_size = len(vocab)\n",
    "rnn_size   = 128\n",
    "num_layers = 2\n",
    "grad_clip  = 5.\n",
    "\n",
    "# Construct RNN model \n",
    "unitcell   = tf.nn.rnn_cell.BasicLSTMCell(rnn_size)\n",
    "cell       = tf.nn.rnn_cell.MultiRNNCell([unitcell] * num_layers)\n",
    "input_data = tf.placeholder(tf.int32, [batch_size, seq_length])\n",
    "targets    = tf.placeholder(tf.int32, [batch_size, seq_length])\n",
    "istate     = cell.zero_state(batch_size, tf.float32)\n",
    "# Weigths \n",
    "with tf.variable_scope('rnnlm'):\n",
    "    softmax_w = tf.get_variable(\"softmax_w\", [rnn_size, vocab_size])\n",
    "    softmax_b = tf.get_variable(\"softmax_b\", [vocab_size])\n",
    "    with tf.device(\"/cpu:0\"):\n",
    "        embedding = tf.get_variable(\"embedding\", [vocab_size, rnn_size])\n",
    "        inputs = tf.split(1, seq_length, tf.nn.embedding_lookup(embedding, input_data))\n",
    "        inputs = [tf.squeeze(_input, [1]) for _input in inputs]\n",
    "# Output\n",
    "def loop(prev, _):\n",
    "    prev = tf.nn.xw_plus_b(prev, softmax_w, softmax_b)\n",
    "    prev_symbol = tf.stop_gradient(tf.argmax(prev, 1))\n",
    "    return tf.nn.embedding_lookup(embedding, prev_symbol)\n",
    "\"\"\"\n",
    "    loop_function: If not None, this function will be applied to the i-th output\n",
    "    in order to generate the i+1-st input, and decoder_inputs will be ignored,\n",
    "    except for the first element (\"GO\" symbol).\n",
    "\"\"\" \n",
    "outputs, last_state = tf.nn.seq2seq.rnn_decoder(inputs, istate, cell\n",
    "                , loop_function=None, scope='rnnlm')\n",
    "output = tf.reshape(tf.concat(1, outputs), [-1, rnn_size])\n",
    "logits = tf.nn.xw_plus_b(output, softmax_w, softmax_b)\n",
    "probs  = tf.nn.softmax(logits)\n",
    "# Loss\n",
    "loss = tf.nn.seq2seq.sequence_loss_by_example([logits], # Input\n",
    "    [tf.reshape(targets, [-1])], # Target\n",
    "    [tf.ones([batch_size * seq_length])], # Weight \n",
    "    vocab_size)\n",
    "# Optimizer\n",
    "cost     = tf.reduce_sum(loss) / batch_size / seq_length\n",
    "final_state = last_state\n",
    "lr       = tf.Variable(0.0, trainable=False)\n",
    "tvars    = tf.trainable_variables()\n",
    "grads, _ = tf.clip_by_global_norm(tf.gradients(cost, tvars), grad_clip)\n",
    "_optm    = tf.train.AdamOptimizer(lr)\n",
    "optm     = _optm.apply_gradients(zip(grads, tvars))\n",
    "\n",
    "print (\"Network Ready\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {
    "collapsed": false,
    "scrolled": true
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[0/8500] cost: 5.1518 / Each batch learning took 6.2978 sec\n",
      "model saved to 'data/linux_kernel/model.ckpt'\n",
      "[100/8500] cost: 3.0705 / Each batch learning took 0.3866 sec\n",
      "[200/8500] cost: 2.5382 / Each batch learning took 0.3910 sec\n",
      "[300/8500] cost: 2.3884 / Each batch learning took 0.5311 sec\n",
      "[400/8500] cost: 2.2029 / Each batch learning took 0.3930 sec\n",
      "[500/8500] cost: 1.9560 / Each batch learning took 0.5088 sec\n",
      "model saved to 'data/linux_kernel/model.ckpt'\n",
      "[600/8500] cost: 1.9134 / Each batch learning took 0.3861 sec\n",
      "[700/8500] cost: 1.7579 / Each batch learning took 0.5502 sec\n",
      "[800/8500] cost: 1.7580 / Each batch learning took 0.4546 sec\n",
      "[900/8500] cost: 1.6952 / Each batch learning took 0.3958 sec\n",
      "[1000/8500] cost: 1.5991 / Each batch learning took 0.4516 sec\n",
      "model saved to 'data/linux_kernel/model.ckpt'\n",
      "[1100/8500] cost: 1.6036 / Each batch learning took 0.3708 sec\n",
      "[1200/8500] cost: 1.4374 / Each batch learning took 0.4035 sec\n",
      "[1300/8500] cost: 1.5513 / Each batch learning took 0.4629 sec\n",
      "[1400/8500] cost: 1.4814 / Each batch learning took 0.5162 sec\n",
      "[1500/8500] cost: 1.4986 / Each batch learning took 0.4023 sec\n",
      "model saved to 'data/linux_kernel/model.ckpt'\n",
      "[1600/8500] cost: 1.4957 / Each batch learning took 0.5584 sec\n",
      "[1700/8500] cost: 1.4569 / Each batch learning took 0.5504 sec\n",
      "[1800/8500] cost: 1.3966 / Each batch learning took 0.4409 sec\n",
      "[1900/8500] cost: 1.3742 / Each batch learning took 0.8715 sec\n",
      "[2000/8500] cost: 1.4071 / Each batch learning took 0.7707 sec\n",
      "model saved to 'data/linux_kernel/model.ckpt'\n",
      "[2100/8500] cost: 1.4037 / Each batch learning took 0.4636 sec\n",
      "[2200/8500] cost: 1.3220 / Each batch learning took 0.6967 sec\n",
      "[2300/8500] cost: 1.3267 / Each batch learning took 0.7644 sec\n",
      "[2400/8500] cost: 1.2870 / Each batch learning took 0.5228 sec\n",
      "[2500/8500] cost: 1.3171 / Each batch learning took 0.5671 sec\n",
      "model saved to 'data/linux_kernel/model.ckpt'\n",
      "[2600/8500] cost: 1.2876 / Each batch learning took 0.5576 sec\n",
      "[2700/8500] cost: 1.2571 / Each batch learning took 0.4314 sec\n",
      "[2800/8500] cost: 1.3123 / Each batch learning took 0.5939 sec\n",
      "[2900/8500] cost: 1.1588 / Each batch learning took 0.6087 sec\n",
      "[3000/8500] cost: 1.2834 / Each batch learning took 0.5066 sec\n",
      "model saved to 'data/linux_kernel/model.ckpt'\n",
      "[3100/8500] cost: 1.2362 / Each batch learning took 0.4319 sec\n",
      "[3200/8500] cost: 1.2768 / Each batch learning took 0.4418 sec\n",
      "[3300/8500] cost: 1.2836 / Each batch learning took 0.6158 sec\n",
      "[3400/8500] cost: 1.2830 / Each batch learning took 0.7412 sec\n",
      "[3500/8500] cost: 1.2296 / Each batch learning took 0.7596 sec\n",
      "model saved to 'data/linux_kernel/model.ckpt'\n",
      "[3600/8500] cost: 1.2142 / Each batch learning took 0.8046 sec\n",
      "[3700/8500] cost: 1.2474 / Each batch learning took 0.8149 sec\n",
      "[3800/8500] cost: 1.2455 / Each batch learning took 0.9514 sec\n",
      "[3900/8500] cost: 1.1910 / Each batch learning took 1.0230 sec\n",
      "[4000/8500] cost: 1.1874 / Each batch learning took 0.7037 sec\n",
      "model saved to 'data/linux_kernel/model.ckpt'\n",
      "[4100/8500] cost: 1.1602 / Each batch learning took 0.6907 sec\n",
      "[4200/8500] cost: 1.1896 / Each batch learning took 0.6589 sec\n",
      "[4300/8500] cost: 1.1680 / Each batch learning took 0.6051 sec\n",
      "[4400/8500] cost: 1.1472 / Each batch learning took 0.4314 sec\n",
      "[4500/8500] cost: 1.2073 / Each batch learning took 0.7571 sec\n",
      "model saved to 'data/linux_kernel/model.ckpt'\n",
      "[4600/8500] cost: 1.0601 / Each batch learning took 0.8487 sec\n",
      "[4700/8500] cost: 1.1822 / Each batch learning took 0.5197 sec\n",
      "[4800/8500] cost: 1.1427 / Each batch learning took 0.5184 sec\n",
      "[4900/8500] cost: 1.1774 / Each batch learning took 0.4620 sec\n",
      "[5000/8500] cost: 1.1902 / Each batch learning took 0.4941 sec\n",
      "model saved to 'data/linux_kernel/model.ckpt'\n",
      "[5100/8500] cost: 1.1960 / Each batch learning took 0.7985 sec\n",
      "[5200/8500] cost: 1.1568 / Each batch learning took 0.7381 sec\n",
      "[5300/8500] cost: 1.1487 / Each batch learning took 0.5911 sec\n",
      "[5400/8500] cost: 1.1710 / Each batch learning took 0.8420 sec\n",
      "[5500/8500] cost: 1.1684 / Each batch learning took 0.7788 sec\n",
      "model saved to 'data/linux_kernel/model.ckpt'\n",
      "[5600/8500] cost: 1.1337 / Each batch learning took 0.7290 sec\n",
      "[5700/8500] cost: 1.1234 / Each batch learning took 1.0153 sec\n",
      "[5800/8500] cost: 1.1034 / Each batch learning took 0.7469 sec\n",
      "[5900/8500] cost: 1.1276 / Each batch learning took 0.7259 sec\n",
      "[6000/8500] cost: 1.1073 / Each batch learning took 0.7722 sec\n",
      "model saved to 'data/linux_kernel/model.ckpt'\n",
      "[6100/8500] cost: 1.0955 / Each batch learning took 0.7700 sec\n",
      "[6200/8500] cost: 1.1489 / Each batch learning took 0.4165 sec\n",
      "[6300/8500] cost: 1.0120 / Each batch learning took 0.7359 sec\n",
      "[6400/8500] cost: 1.1296 / Each batch learning took 0.6871 sec\n",
      "[6500/8500] cost: 1.0963 / Each batch learning took 0.6530 sec\n",
      "model saved to 'data/linux_kernel/model.ckpt'\n",
      "[6600/8500] cost: 1.1259 / Each batch learning took 0.4506 sec\n",
      "[6700/8500] cost: 1.1422 / Each batch learning took 0.3957 sec\n",
      "[6800/8500] cost: 1.1431 / Each batch learning took 0.4530 sec\n",
      "[6900/8500] cost: 1.1168 / Each batch learning took 0.4068 sec\n",
      "[7000/8500] cost: 1.1119 / Each batch learning took 1.0343 sec\n",
      "model saved to 'data/linux_kernel/model.ckpt'\n",
      "[7100/8500] cost: 1.1255 / Each batch learning took 0.4080 sec\n",
      "[7200/8500] cost: 1.1266 / Each batch learning took 0.3840 sec\n",
      "[7300/8500] cost: 1.1036 / Each batch learning took 0.8628 sec\n",
      "[7400/8500] cost: 1.0860 / Each batch learning took 0.4150 sec\n",
      "[7500/8500] cost: 1.0681 / Each batch learning took 0.4738 sec\n",
      "model saved to 'data/linux_kernel/model.ckpt'\n",
      "[7600/8500] cost: 1.0921 / Each batch learning took 0.4141 sec\n",
      "[7700/8500] cost: 1.0728 / Each batch learning took 0.3944 sec\n",
      "[7800/8500] cost: 1.0644 / Each batch learning took 0.4473 sec\n",
      "[7900/8500] cost: 1.1155 / Each batch learning took 0.4841 sec\n",
      "[8000/8500] cost: 0.9819 / Each batch learning took 0.4198 sec\n",
      "model saved to 'data/linux_kernel/model.ckpt'\n",
      "[8100/8500] cost: 1.0945 / Each batch learning took 0.4452 sec\n",
      "[8200/8500] cost: 1.0682 / Each batch learning took 0.4038 sec\n",
      "[8300/8500] cost: 1.0939 / Each batch learning took 0.4889 sec\n",
      "[8400/8500] cost: 1.1111 / Each batch learning took 0.3995 sec\n"
     ]
    }
   ],
   "source": [
    "# Train the model!\n",
    "num_epochs    = 50\n",
    "save_every    = 500\n",
    "learning_rate = 0.002\n",
    "decay_rate    = 0.97\n",
    "\n",
    "sess = tf.Session()\n",
    "sess.run(tf.initialize_all_variables())\n",
    "summary_writer = tf.train.SummaryWriter(save_dir, graph=sess.graph)\n",
    "saver = tf.train.Saver(tf.all_variables())\n",
    "init_time = time.time()\n",
    "for epoch in range(num_epochs):\n",
    "    # Learning rate scheduling \n",
    "    sess.run(tf.assign(lr, learning_rate * (decay_rate ** epoch)))\n",
    "    state     = sess.run(istate)\n",
    "    batchidx  = 0\n",
    "    for iteration in range(num_batches):\n",
    "        start_time   = time.time()\n",
    "        randbatchidx = np.random.randint(num_batches)\n",
    "        xbatch       = xbatches[batchidx]\n",
    "        ybatch       = ybatches[batchidx]\n",
    "        batchidx     = batchidx + 1\n",
    "        \n",
    "        # Note that, num_batches = len(xbatches)\n",
    "        # Train! \n",
    "        train_loss, state, _ = sess.run([cost, final_state, optm]\n",
    "            , feed_dict={input_data: xbatch, targets: ybatch, istate: state}) \n",
    "        total_iter = epoch*num_batches + iteration\n",
    "        end_time     = time.time();\n",
    "        duration     = end_time - start_time\n",
    "        \n",
    "        if total_iter % 100 == 0:\n",
    "            print (\"[%d/%d] cost: %.4f / Each batch learning took %.4f sec\" \n",
    "                   % (total_iter, num_epochs*num_batches, train_loss, duration))\n",
    "        if total_iter % save_every == 0: \n",
    "            ckpt_path = os.path.join(save_dir, 'model.ckpt')\n",
    "            saver.save(sess, ckpt_path, global_step = total_iter)\n",
    "            # Save network! \n",
    "            print(\"model saved to '%s'\" % (ckpt_path)) "
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Run the command line\n",
    "##### tensorboard --logdir=/tmp/tf_logs/char_rnn_tutorial\n",
    "### Open http://localhost:6006/ into your web browser"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Done!! It took 5238.4040 second. \n"
     ]
    }
   ],
   "source": [
    "print (\"Done!! It took %.4f second. \" %(time.time() - init_time))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false
   },
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 2",
   "language": "python",
   "name": "python2"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 2
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython2",
   "version": "2.7.6"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 0
}
